<template>
  <div>
    <a-page-header class="pt-0" @back="back" :title="t('填写表单')"></a-page-header>
    <a-spin :spinning="table.loading" class="w-[100%]">
      <a-form
        layout="vertical"
        @finish="submit"
        :rules="formRules"
        :model="form"
        ref="formRef"
        :label-col="{ span: 4 }"
        :wrapper-col="{ span: 12 }"
      >
        <a-card :bordered="false" :body-style="{ paddingTop: '0' }">
          <a-form-item :wrapper-col="{ span: 24 }" :label="t('素材尺寸')" help="必须先选尺寸">
            <LibrarySizeOptions v-model="form.sizeId" />
          </a-form-item>
          <template v-if="form.sizeId">
            <a-form-item :label="t('文件类型')">
              <MaterialFileType v-model="form.type" />
            </a-form-item>
            <a-form-item :label="t('素材类型')">
              <MaterialCategory v-model="form.word" />
            </a-form-item>
            <a-form-item :label="t('上传文件')" :wrapper-col="{ span: 16 }">
              <div class="flex gap-4 items-center h-full">
                <a-upload-dragger
                  class="flex-1"
                  name="file"
                  v-model:fileList="fileList"
                  multiple
                  :maxCount="1"
                  :beforeUpload="() => false"
                  :accept="accept()"
                  @change="setUri"
                  :headers="{
                    Authorization: `Bearer ${getToken()}`,
                  }"
                >
                  <slot>
                    <p class="ant-upload-drag-icon">
                      <inbox-outlined></inbox-outlined>
                    </p>
                    <p class="ant-upload-hint">在这里上传文件</p>
                    <p class="ant-upload-hint">支持点击和拖拽</p>
                  </slot>
                </a-upload-dragger>
                <File :item="form" v-if="form.uri" />
                <div v-if="form.type === '1' && form.cover">
                  <div class="mb-4">{{ t('视频封面') }}</div>
                  <XImage :src="form.cover" :width="100"></XImage>
                </div>
              </div>
            </a-form-item>
            <a-form-item :label="t('素材名称')" name="name">
              <a-input v-model:value="form.name" class="w-fit" allow-clear></a-input>
            </a-form-item>

            <a-form-item :label="t('是否共享')">
              <LocalOptions v-model="form.share" :option="SYSTEM_OPTION_TYPE.IS"></LocalOptions>
            </a-form-item>
            <div class="flex gap-4">
              <a-button type="primary" htmlType="submit">{{ t('保存') }}</a-button>
              <a-button @click="reset">{{ t('重置') }}</a-button>
            </div>
          </template>
        </a-card>
      </a-form>
    </a-spin>
    <canvas id="canvas" style="display: none" :width="320" height="240"></canvas>
  </div>
</template>

<script setup lang="ts">
import type { IResponse } from '@/api/config/types';
import { list } from '../data/curd';
import { allowEditMenu, table } from '../data/data';
import { formRef, form, formRules } from '../data/form';
const { t } = useI18n();
import { nanoid } from 'nanoid';
import { message } from 'ant-design-vue';
import useUserStore from '@/store/user';
import { ossUpload, uploadToServer } from '@/api/modules/utils/files';
import { base64toFile } from '@/utils/file/file';
import { getToken } from '@/store/user/utils';
import { createLibrary, updateLibrary } from '@/api/modules/data/library';
import { listLibrarySizeOptions } from '@/api/modules/utils/data';
import type { IResolution } from '@/api/modules/data/resolution';
import { SYSTEM_OPTION_TYPE } from '@/enum/system';

const VIDEO_LIMIT = 5 * 1024 * 1024 * 1024 * 2024;
const fileList = ref<any[]>([]);
const loading = ref(false);
const store = useUserStore();
const back = () => {
  allowEditMenu.value = false;
  reset();
};
const accept = () => {
  const mime: any = {
    '0': 'image/*',
    '1': 'video/mp4,video/avi',
    '2': '.ttf, .otf, .woff, .woff2',
  };
  return mime[form.value.type];
};
const getResolution = (): IResolution | undefined => {
  const target = listLibrarySizeOptions.value.find(e => {
    if (e.value === form.value.sizeId) {
      return e;
    }
    return null;
  });

  if (target) {
    // @ts-ignore
    return target.raw;
  }
};

const uploadFile = async (file: File): Promise<string | undefined> => {
  if (!file) return;
  let href = '';

  if (store.$state.oss) {
    const { url } = await ossUpload({
      file,
      type: form.value.type,
    });

    form.value.uri = url;

    form.value.bytes = file?.size || 0;
    href = url;
  } else {
    /* 上传到本地 */
    const { type } = form.value;
    const url = store.$state.paths[type];

    const { data } = await uploadToServer(`${url}`, file);

    if (data.code === 500) {
      loading.value = false;
      message.warning(data.msg);
    } else {
      message.success(data.msg);
      href = data.data;
    }
  }
  return href;
};
const checkResource = (file: File) => {
  const sizeInfo = getResolution();
  if (!sizeInfo) return;

  return new Promise(res => {
    if (form.value.type === '0') {
      const image = new Image();

      if (!file) return;
      image.src = URL.createObjectURL(file);

      image.onload = () => {
        if (image.width === sizeInfo.width && image.height === sizeInfo.height) {
          res(true);
        }
        res(false);
      };
    } else if (form.value.type === '1') {
      if (file.size > VIDEO_LIMIT) {
        message.info(`请选择小于5M的视频`);
        res(false);
        return;
      }
      const video = document.createElement('video');
      video.src = URL.createObjectURL(file);
      video.hidden = true;
      video.muted = true;
      video.autoplay = true;
      const canvas = document.getElementById('canvas') as HTMLCanvasElement;
      const context = canvas.getContext('2d')!;

      video.addEventListener('loadeddata', async () => {
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        const base64 = canvas.toDataURL('image/webp').replace(`data:image/webp;base64,`, '');

        const cover = base64toFile(base64, `${nanoid()}.png`);
        if (canvas.width === sizeInfo.width && canvas.height === sizeInfo.height) {
          const coverData = await uploadFile(cover);
          const videoData = await uploadFile(file);
          if (coverData) {
            form.value.cover = coverData;
          }
          if (videoData) {
            form.value.uri = videoData;
          }
        }
      });
      video.onloadedmetadata = () => {
        const width = video.videoWidth;
        const height = video.videoHeight;
        if (width === sizeInfo.width && height === sizeInfo.height) {
          res(true);
          return;
        }
        res(false);
      };
    }
  });
};
const setUri = async () => {
  const file = fileList.value[0];
  form.value.cover = '';
  form.value.name = file.name;
  const result = await checkResource(file.originFileObj);
  if (!result) {
    message.warning('素材尺寸不符合要求');
    form.value.uri = '';
    fileList.value = [];
    return;
  }
  if (fileList.value.length === 1) {
    form.value.name = file.name || 'Untitled';
    form.value.uri = nanoid(12);
  }
};
const submit = async () => {
  let result: IResponse | undefined = undefined;
  const file = fileList.value[0];

  /* 创建新的素材 */
  if (!form.value.resId) {
    const url = await uploadFile(file.originFileObj);
    if (url) {
      form.value.uri = url;
    }
    const { data } = await createLibrary(form.value);
    result = data;
  } else {
    /* 更新 */
    const { data } = await updateLibrary(form.value);
    result = data;
  }

  await list();
  back();
};
const reset = () => {
  formRef.value?.resetFields();
};
</script>

<style lang="scss" scoped>
:deep(.ant-card) {
  box-shadow: none !important;
}
</style>
